package top.tangyh.lamp.common.utils;

import java.text.SimpleDateFormat;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.pagehelper.util.StringUtil;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

public class YDateUtils {
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public final static String DATE_TIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm";

    public final static String DATE_TIME_HOUR_PATTERN = "yyyy-MM-dd HH";

    public static final String DATE = "yyyy-MM-dd";

    public static final String TIME = "HH:mm:ss";

    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");

    static final long nd = 1000 * 24 * 60 * 60;
    static final long nh = 1000 * 60 * 60;

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date    日期
     * @param pattern 格式，如：DateUtils.DATE_TIME_PATTERN
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 字符串转换成日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期的格式，如：DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }

        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }

    /**
     * 根据周数，获取开始日期、结束日期
     *
     * @param week 周期  0本周，-1上周，-2上上周，1下周，2下下周
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getWeekStartAndEnd(int week) {
        DateTime dateTime = new DateTime();
        LocalDate date = new LocalDate(dateTime.plusWeeks(week));

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

    /**
     * 对日期的【秒】进行加/减
     *
     * @param date    日期
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addDateSeconds(Date date, int seconds) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusSeconds(seconds).toDate();
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param date    日期
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(Date date, int minutes) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMinutes(minutes).toDate();
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(Date date, int hours) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hours).toDate();
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(Date date, int days) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(days).toDate();
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param date  日期
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(Date date, int weeks) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusWeeks(weeks).toDate();
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(months).toDate();
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param date  日期
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addDateYears(Date date, int years) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusYears(years).toDate();
    }

    /**
     * 将字符串转为 date
     */
    public static Date strToDate(String time, String format) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
            return simpleDateFormat.parse(time);
        } catch (ParseException e) {
            return null;
        }
    }


    /**
     * 获取两个时间相差的天数
     */
    public static Integer getMinusDay(String time) {
        long nd = 1000 * 24 * 60 * 60;
        long diff = System.currentTimeMillis() - Objects.requireNonNull(strToDate(time, DATE_TIME_PATTERN)).getTime();
        return Math.toIntExact((diff / nd) + 1);
    }


    /**
     * 判断time是否和当前时间是同一天
     */
    public static boolean isOneDay(String nowTime, String time) {
        if (nowTime.substring(8, 11).trim().equals(time.substring(8, 11).trim())) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 根据当前时间 速度 计算完成时间
     */
    public static String getFinishTime(Integer speed, Double surplus, Date date) {
        BigDecimal decimalHour = new BigDecimal(1000 * 60 * 60);
        BigDecimal decimal1 = new BigDecimal(speed);
        if (decimal1.intValue() == 0) {
            decimal1 = BigDecimal.ONE;
        }
        BigDecimal decimal2 = new BigDecimal(surplus);
        BigDecimal decimal3 = decimal2.divide(decimal1, 6, RoundingMode.HALF_UP).multiply(decimalHour);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Long time = date.getTime() + decimal3.longValue();
        return sdf.format(time);
    }

    /**
     * 获取两个时间点的时间差 为分
     * @return
     */
    public static long getMinus(Date currentDate, Date caoZuoShiJian) {
        if (caoZuoShiJian==null){
            return 0;
        }
        try {
            long nm = 1000 * 60;
            //当前时间 减去 操作时间
            long diff = currentDate.getTime() - caoZuoShiJian.getTime();
            return diff / nm;
        }catch (Exception e){
            e.printStackTrace ();
            return 0;
        }
    }


    /**
     * 获取两个时间点的时间差 为小时
     * @return
     */
    public static long getHours(Date currentDate, Date caoZuoShiJian) {
        if (caoZuoShiJian==null){
            return 0;
        }
        try {
            long nm = 1000 * 60*60;
            //当前时间 减去 操作时间
            long diff = currentDate.getTime() - caoZuoShiJian.getTime();
            return diff / nm;
        }catch (Exception e){
            e.printStackTrace ();
            return 0;
        }
    }

    /**
     * 获取两个时间点的时间差 为小时
     */
    public static double getMinusHour(Date currentDate, Date caoZuoShiJian) {
        if (caoZuoShiJian == null) {
            return (double) 0;
        }
        try {
            long nd = 1000 * 24 * 60 * 60;
            long nh = 1000 * 60 * 60;
            //当前时间 减去 操作时间
            long diff = currentDate.getTime() - caoZuoShiJian.getTime();
            return (double) diff % nd / nh;
        } catch (Exception e) {
            e.printStackTrace();
            return 0.00;
        }
    }

    /**
     * 获取两个时间点的时间差 为天
     *
     */
    public static int getDay(Date currentDate, Date caoZuoShiJian) {
        if (caoZuoShiJian==null){
            return 0;
        }
        try {
            long nd = 1000 * 24 * 60 * 60;
            //当前时间 减去 操作时间
            long diff = currentDate.getTime() - caoZuoShiJian.getTime();
            return (int) (diff / nd);
        }catch (Exception e){
            e.printStackTrace ();
            return 0 ;
        }
    }


    /**
     * 截取时间 小时位
     */
    public static Integer getHourStr(String time) {
        return Integer.valueOf(time.substring(11, 13).trim());
    }

    /**
     * 获取当前天的分钟数
     */
    public static Integer getDayMinuteCount(String time) {
        return Integer.valueOf(time.substring(11, 13).trim())*60+Integer.valueOf(time.substring(14, 16).trim());
    }

    /**
     * 根据 当前时间 减去操作时间 得出走了多少秒 计算出最后一段用药已经走到的时间
     */
    public static String getUsedTime(String time, Integer minute) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(Objects.requireNonNull(strToDate(time, DATE_TIME_PATTERN)));
        cal.add(Calendar.MINUTE, minute);
        return dateToStr(cal.getTime());
    }


    /**
     * 上一个整点
     */
    public static String addTime(String time, Integer num) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(Objects.requireNonNull(strToDate(time, DATE_TIME_PATTERN)));
        cal.add(Calendar.HOUR_OF_DAY, num);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return dateToStr(cal.getTime());
    }


    /**
     * 获取当前时间的 下一天0时0分0秒
     */
    public static String getNextDayStartTime(String time) {
        Calendar cal = Calendar.getInstance();
        cal.setTime((strToDate(time, DATE_TIME_PATTERN)));
        cal.add(Calendar.DATE, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return dateToStr(cal.getTime());
    }

    public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    public static long getTimestampOfDateTime(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return instant.toEpochMilli();
    }

    /**
     * 截取时间字符串时分秒
     */
    public static Date getTime(String time) {
        return strToDate(time.substring(11).trim(), TIME);
    }


    /**
     * 返回当前小时的 0分0秒
     */
    public static Date getHourStart(String hour) {
        return strToDate((hour.length() == 1 ? 0 + hour : hour) + ":00:00", TIME);
    }

    /**
     * 获取当前小时的59分59秒
     */
    public static Date getHourEnd(String hour) {
        return strToDate((hour.length() == 1 ? 0 + hour : hour) + ":59:59", TIME);
    }

    /**
     * 返回天数字符串
     */
    public static String dateToDayStr(Date date) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE);
            return simpleDateFormat.format(date);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 日期转字符串
     */
    public static String dateToStr(Date date) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_TIME_PATTERN);
            return simpleDateFormat.format(date);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 日期转字符串
     */
    public static String dateToDateStr(Date date) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE);
            return simpleDateFormat.format(date);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 判断字符串是否是日期格式
     */
    public static boolean judgeIsDateStr(String DateStr) {
        boolean flag = true;
        try {
            SDF.parse(DateStr);
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }

    /**
     * 根据传入日期 生成一天整点的时间
     */
    public static List<String> getTimeList(String time) {
        List<String> timeList = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            timeList.add(time + " " + addZero(String.valueOf(i)) + ":00:00");
        }
        return timeList;
    }

    /**
     * 判断小时位是单个的话补0
     */
    public static String addZero(String str) {
        if (str.length() == 1) {
            return "0" + str;
        } else {
            return str;
        }
    }




    public static long getDays(Date beginDateTime, Date endDateTime) {
        return (endDateTime.getTime() - beginDateTime.getTime()) / (24 * 60 * 60 * 1000);
    }

    public static String getPercentage(long divisor, long dividend, int n, int resultType) {
        if (divisor == 0) {
            if (resultType == 0) {
                return "0";
            } else {
                return "100";
            }
        } else if (dividend == 0) {
            return "数据不符合实际情况，检查数据库";
        }
        // 创建一个数值格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后n位
        numberFormat.setMaximumFractionDigits(n);
        return numberFormat.format((float) divisor / (float) dividend * 100);
    }

    public static String getPermille(long divisor, long dividend, int n, int resultType) {
        if (divisor == 0) {
            if (resultType == 0) {
                return "0";
            } else {
                return "1000";
            }
        } else if (dividend == 0) {
            return "数据不符合实际情况，检查数据库";
        }
        // 创建一个数值格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后n位
        numberFormat.setMaximumFractionDigits(n);
        return numberFormat.format((float) divisor / (float) dividend * 1000);
    }

    /**
     * 时间戳转换成日期格式字符串
     *
     * @param seconds 精确到秒的字符串
     * @param format
     * @return
     */
    public static String timeStamp2Date(String seconds, String format) {
        if (seconds == null || seconds.isEmpty() || seconds.equals("null")) {
            return "";
        }
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date(Long.valueOf(seconds + "000")));
    }

    /**
     * 表两个时间差
     */
    public static int compareTwoTime(Date time1, Date time2) {
        int flagValue = 0;
        try {
            long millisecond = time1.getTime() - time2.getTime();
            if (millisecond > 0) {
                flagValue = 1;
            } else if (millisecond < 0) {
                flagValue = -1;
            } else if (millisecond == 0) {
                flagValue = 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (flagValue);
    }

    /**
     * 判断时间是否在时间段内 时间大于 小于
     *
     * @param nowTime
     * @param beginTime
     * @param endTime
     * @return
     */
    public static boolean belongCalendar(Date nowTime, Date beginTime, Date endTime) {
//        Calendar date = Calendar.getInstance();
//        date.setTime(nowTime);
//
//        Calendar begin = Calendar.getInstance();
//        begin.setTime(beginTime);
//
//        Calendar end = Calendar.getInstance();
//        end.setTime(endTime);

//        if (date.after(begin) && date.before(end)) {
//            return true;
//        } else {
//            return false;
//        }
        if(nowTime.getTime()>=beginTime.getTime()&&nowTime.getTime()<=endTime.getTime()){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 实现 时间的大于等于和小于等于
     * @param nowTime
     * @param beginTime
     * @param endTime
     * @return
     */
    public static boolean belongCalendarAndEqual(Date nowTime, Date beginTime, Date endTime) {
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(beginTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if ( (date.after(begin) ||date.equals(begin))&&(date.before(end)||date.equals(end)) ) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 获取当前时间的小时和分
     * @param currentDate
     * @return
     */
    public static String getCurrentHourAndMinute(Date currentDate){
        Calendar cal = Calendar.getInstance();//使用日历类

        cal.setTime(currentDate);

        int nowHour = cal.get(Calendar.HOUR_OF_DAY);

        int nowMin = cal.get(Calendar.MINUTE);
        return nowHour+"小时"+nowMin+"分支";
    }

    /**
     * 获取当前时间的小时和分+指定小时
     * @param currentDate
     * @param hour
     * @return
     */
    public static String getCurrentHourAndMinute(Date currentDate,int hour){
        Calendar cal = Calendar.getInstance();//使用日历类

        cal.setTime(currentDate);

        int nowHour = cal.get(Calendar.HOUR_OF_DAY);

        int nowMin = cal.get(Calendar.MINUTE);
        nowHour=nowHour+hour;
        return nowHour+"小时"+nowMin+"分支";
    }

    /**
     * 得到当前分钟
     * @param currentDate
     * @return
     */
    public static int getCurrentMinute(Date currentDate ){
        Calendar cal = Calendar.getInstance();//使用日历类

        cal.setTime(currentDate);

        int nowMin = cal.get(Calendar.MINUTE);


        return nowMin;
    }

    /**
     * 得到当前小时
     * @param currentDate
     * @return
     */
    public static int getCurrentHour (Date currentDate ){
        Calendar cal = Calendar.getInstance();//使用日历类

        cal.setTime(currentDate);

        int nowHour = cal.get(Calendar.HOUR_OF_DAY);


        return nowHour;
    }

    public static String getDatePoor(Date endDate, Date startDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;

         long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - startDate.getTime();

        // 计算差多少天
//        long day = diff / nd;

        // 计算差多少小时
        long hour = diff % nd / nh;

        // 计算差多少分钟
        long min = diff % nd % nh / nm;

        // 计算差多少秒//输出结果
         long sec = diff % nd % nh % nm / ns;

        return hour + "小时" + min + "分钟"+sec+"秒";
    }


    /**
     * 根据开始时间和结束时间返回时间段内的时间集合
     *
     * @param beginDate
     * @param endDate
     * @return List
     */
    public static List<String> getDatesBetweenTwoDate(Date beginDate, Date endDate) {
        List<String> lDate = new ArrayList<String>();
        lDate.add(DateUtil.formatDate(beginDate));// 把开始时间加入集合
        Calendar cal = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        cal.setTime(beginDate);
        boolean bContinue = true;
        while (bContinue) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            cal.add(Calendar.DAY_OF_MONTH, 1);
            // 测试此日期是否在指定日期之后
            if (endDate.after(cal.getTime())) {
                lDate.add(DateUtil.formatDate(cal.getTime()));
            } else {
                break;
            }
        }
        lDate.add(DateUtil.formatDate(endDate));// 把结束时间加入集合
        return lDate;
    }


    /**
     * 将 Date 转为 LocalDateTime
     *
     * @param date
     * @return java.time.LocalDateTime;
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }


    public static void main(String[] args) {
        GregorianCalendar calendar = new GregorianCalendar();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        System.out.println("hour=" + hour);

    }

    public static String trimNoZeros(String str){
        String result ="";
        if(StringUtil.isNotEmpty(str)){
            BigDecimal value = new BigDecimal(str);
            BigDecimal noZeros = value.stripTrailingZeros();
            result = noZeros.toPlainString();
        }

        return result;
    }

    /**
     * 最大值
     */
    public static BigDecimal max(List<BigDecimal> list) {
        if(null ==list) {
            return null;
        }
//        BigDecimal max = Collections.max(list);

        BigDecimal sum = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            sum = sum.max(list.get(i));
        }
        return sum;
    }

    public static  LocalDateTime timestamToDatetime(long timestamp){
        Instant instant = Instant.ofEpochMilli(timestamp);
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
}
